home *** CD-ROM | disk | FTP | other *** search
- ; Wb-tree File Based Associative String Data Base System.
- ; Copyright (c) 1991, 1992, 1993 Holland Mark Martin
- ;
- ;Permission to use, copy, modify, and distribute this software and its
- ;documentation for educational, research, and non-profit purposes and
- ;without fee is hereby granted, provided that the above copyright
- ;notice appear in all copies and that both that copyright notice and
- ;this permission notice appear in supporting documentation, and that
- ;the name of Holland Mark Martin not be used in advertising or
- ;publicity pertaining to distribution of the software without specific,
- ;written prior consent in each case. Permission to incorporate this
- ;software into commercial products can be obtained from Jonathan
- ;Finger, Holland Mark Martin, 174 Middlesex Turnpike, Burlington, MA,
- ;01803-4467, USA. Holland Mark Martin makes no representations about
- ;the suitability or correctness of this software for any purpose. It
- ;is provided "as is" without express or implied warranty. Holland Mark
- ;Martin is under no obligation to provide any services, by way of
- ;maintenance, update, or otherwise.
-
- (require (in-vicinity (program-vicinity) "sys"))
-
- (define trace-on #f)
-
- (define (match-str pkt)
- (case (MATCH-TYPE pkt)
- ((QPASTP) "QPASTP")
- ((PASTP) "PASTP")
- ((MATCH) "MATCH")
- ((MATCHEND) "MATCHEND")
- ((PASTEND) "PASTEND")
- (else ">>>>ERROR<<<<")))
-
- ;; CHAIN-PREV-FIND [was CHAIN-FIND-PREV] searches fwd from ENT looking for
- ;; key preceeding KEY-STR.
- ;; call with ENT in mode ACCESS, prev-ent=#f, prev-pos=0
- ;; if found, returns an ENT in mode ACCESS (match pos is in PKT, type=MATCH);
- ;; otherwise, returns an ENT in mode ACCESS, match type=PASTEND, POS=0
-
- (define (chain-prev-find ent access key-str k-len pkt prev-ent prev-pos)
- (let ((blk (ENT-BLK ent)))
- (blk-find-pos blk key-str k-len pkt)
- (if trace-on
- (fprintf diagout "c-f-p blk=%d res=[%s mpos=%d kpos=%d ppos=%d] prev-ent=%d:%ld ppos=%d\\n"
- (BLK-ID blk) (match-str pkt) (MATCH-POS pkt) (KEY-POS pkt) (PREV-MATCH-POS pkt)
- (and prev-ent (ENT-SEG prev-ent)) (and prev-ent (ENT-ID prev-ent)) prev-pos))
- (cond ((and (eq? (MATCH-TYPE pkt) PASTEND) (not (END-OF-CHAIN? blk)))
- (let* ((nxt-num (BLK-NXT-ID blk))
- (seg (ENT-SEG ent))
- (nent #f)
- (empty-blk? (eq? (MATCH-POS pkt) BLK-DATA-START))
- (ppos (if empty-blk?
- prev-pos
- ;(blk-prev-key blk (MATCH-POS pkt))
- (PREV-MATCH-POS pkt)
- )))
- (if trace-on
- (fprintf diagout "c-f-p nxt=%d empty=%d ppos=%d\\n"
- nxt-num empty-blk? ppos))
- (cond (empty-blk?
- (release-ent! ent access))
- (else
- (if prev-ent (release-ent! prev-ent #f))
- (ent-update-access ent access #f)
- (set! prev-ent ent)))
- (set! nent (get-ent seg nxt-num access))
- (chain-prev-find nent access key-str k-len pkt prev-ent ppos)))
- ((eq? (MATCH-POS pkt) BLK-DATA-START) ; KEY found, but
- ; PREV(KEY) in prev block
- (cond (prev-ent
- (release-ent! ent access)
- (ent-update-access prev-ent #f access) ;need to back out if #f
- (SET-MATCH-TYPE! pkt MATCH)
- (if trace-on
- (fprintf diagout "cfp-res1=MATCH at %d pos=%d\\n"
- (ENT-ID prev-ent) prev-pos))
- (SET-MATCH-POS! pkt prev-pos)
- prev-ent)
- (else
- (SET-MATCH-TYPE! pkt PASTEND)
- (if trace-on
- (fprintf diagout "cfp-res3=PASTEND prev-ent=NONE pos=%d\\n"
- prev-pos))
- (SET-MATCH-POS! pkt 0)
- ent)))
- (else ; found, current block
- (if prev-ent (release-ent! prev-ent #f))
- (SET-MATCH-TYPE! pkt MATCH)
- (SET-MATCH-POS! pkt (PREV-MATCH-POS pkt))
- ; (SET-MATCH-POS! pkt (blk-prev-key blk (MATCH-POS pkt)))
- (if trace-on
- (fprintf diagout "cfp-res2=MATCH at %d pos=%d\\n"
- (BLK-ID blk) (MATCH-POS pkt)))
- ent))))
-
- (define (str-gtr? a-str a-pos a-len b-str b-pos b-len)
- (let loop ((i 0) (ap a-pos) (bp b-pos))
- (cond ((>= i a-len) #f)
- ((>= i b-len) #t)
- ((char<? (string-ref a-str ap) (string-ref b-str bp)) #f)
- ((char<? (string-ref b-str bp) (string-ref a-str ap)) #t)
- (else (loop (+ i 1) (+ ap 1) (+ bp 1))))))
-
- ;; PREV-KEY-ENT [was PREV-KEY] assumes entry with #f access to BLK.
- ;; It either returns the entry contining PREV(key) (with READ access)
- ;; (and pos(prev) in PKT, type=MATCH) or #f, if there is no such key.
- ;; call PREV-KEY-ENT with ROOT block...
-
- ;; NOTE: PREV-K-ENT still needs the PENT kluge to keep the block unchanged while it works.
-
- (define (prev-k-ent ent key-str k-len level pkt)
- (and ent ; this is also not an "error"
- ; keep ptr to blk till we verify its PREV...
- (let ((pent (get-ent (ENT-SEG ent) (ENT-ID ent) #f)))
- (set! ent (chain-prev-find ent ACCREAD key-str k-len pkt #f 0))
- (if trace-on
- (fprintf diagout "prev-key-ent now at blk=%d:%ld cfp: res=[%s mpos=%d kpos=%d ppos=%d]\\n"
- (and ent (ENT-SEG ent)) (and ent (ENT-ID ent))
- (match-str pkt) (MATCH-POS pkt) (KEY-POS pkt) (PREV-MATCH-POS pkt)))
- ; "[and ent" deleted -- rjz
- (let ((res-ent (if (eq? (MATCH-TYPE pkt) MATCH)
- ent
- (begin
- (release-ent! ent ACCREAD)
- (prev-k-ent (prev-blk-ent pent level)
- key-str k-len level pkt)))))
- (release-ent! pent #f)
- res-ent))))
-
- (define (prev-key-ent ent key-str k-len level pkt)
- (if trace-on
- (and ent
- (fprintf diagout "prev-key-ent called key=%.*s level=%d blk=%d:%ld\\n"
- (max 0 k-len) key-str level (ENT-SEG ent) (ENT-ID ent))))
- (and
- ent
- (prev-k-ent (find-prev-ent ent level -1 key-str k-len) key-str k-len level pkt)))
-
- ;; CHAIN-TO-PREV-ENT: subroutine for PREV-BLK-ENT
- ;; this routine chains fwd from FROM-ENT to imm predecessor of GOAL-BLK
- ;; called with FROM-ENT open with ACCREAD; assumes GOAL-BLOCK-NO Name-locked
- ;; returns an ENT open ACCREAD unless missed block, which returns #f
- ;; (routine also checks if its past key)
-
- (define (chain-to-prev-ent from-ent goal-blk-num goal-key-str key-len)
- (let ((from-blk (ENT-BLK from-ent)))
- (if trace-on (fprintf diagout "chain-to-prev-ent from %d:%ld to %d\\n"
- (ENT-SEG from-ent) (ENT-ID from-ent) goal-blk-num))
- (if (= (BLK-NXT-ID from-blk) goal-blk-num) from-ent
- (if (END-OF-CHAIN? from-blk)
- (begin (fprintf diagout
- ">>>>ERROR<<<< chain-to-prev-ent: hit end of %d:ld lev=%d %.*s\\n"
- (ENT-ID from-ent) goal-blk-num (BLK-LEVEL from-blk) key-len goal-key-str)
- #f)
- (let ((b-pos BLK-DATA-START))
- (if (str-gtr? from-blk (+ b-pos 2) (FIELD-LEN from-blk (+ b-pos 1))
- goal-key-str 0 key-len)
- (begin
- (fprintf diagout
- ">>>>ERROR<<<< chain-to-prev-ent: missed blk %d:ld lev=%d %.*s\\n"
- (ENT-ID from-ent) goal-blk-num (BLK-LEVEL from-blk) key-len goal-key-str)
- #f)
- (chain-to-prev-ent
- (switch-ent from-ent ACCREAD (BLK-NXT-ID from-blk) ACCREAD)
- goal-blk-num goal-key-str key-len )))))))
-
- ;; there must be a more efficient way to check this !!!
- (define (at-root-level? seg blk)
- (if (ROOT? blk) #t
- (let* ((rent (get-ent seg (BLK-TOP-ID blk) ACCREAD))
- (rblk (ENT-BLK rent))
- (rlevel (BLK-LEVEL rblk))
- (res (= (BLK-LEVEL blk) rlevel)))
- (if trace-on
- (fprintf diagout "at-root-level blk=%d:%ld rootlvl=%d result=%d\\n"
- seg (BLK-ID blk) rlevel res))
- (release-ent! rent ACCREAD)
- res)))
-
- ;; PREV-BLK-ENT [was PREV-BLK] is called with ENT (with #f access)
- ;; which IS PRESERVED. IT finds the block that precedes ENT, or #f.
- ;; It returns a (second) entry with READ access or #f.
- ;;; TBD - shouldn't it release ENT if returning #f?
- ;; (no, not as things are now -- rjz)
-
- (define (prev-blk-ent ent level)
- (ent-update-access ent #f ACCREAD) ;need to back out if #f
- (let* ((blk (ENT-BLK ent)))
- (if trace-on (fprintf diagout "prev-blk-ent blk=%d:%ld level=%d\\n"
- (ENT-SEG ent) (ENT-ID ent) level))
- (ent-update-access ent ACCREAD #f)
- (if
- (ROOT? blk) #f ;this is not an error, its AT-START-OF-TREE
- (let ((skey-pos (split-key-pos blk)))
- (and
- skey-pos
- (let* ((top-num (BLK-TOP-ID blk))
- (seg (ENT-SEG ent))
- (goal-blk-num (ENT-ID ent))
- (new-str (make-string 256))
- (k-len (recon-this-key blk skey-pos new-str 0 256)))
- (if
- (at-root-level? seg blk)
- (begin
- (fprintf diagout "PREV-BLK-ENT code which has never been run!!!!!\\n")
- (chain-to-prev-ent (get-ent seg top-num ACCREAD)
- goal-blk-num new-str k-len))
- (let ((pkt (make-vector PKT-SIZE)))
- (if trace-on
- (fprintf diagout "prev-blk-ent calling prev-key-ent key= %.*s\\n"
- (max 0 k-len) new-str))
- (set! ent (prev-key-ent (get-ent seg top-num #f)
- new-str k-len (+ level 1) pkt))
- (if (eq? ent #f) #f
- (let ((nxt-pos (next-field (ENT-BLK ent) (+ 1 (MATCH-POS pkt)))))
- (chain-to-prev-ent
- (switch-ent
- ent ACCREAD
- (str2long
- (ENT-BLK ent)
- (if (= nxt-pos (BLK-END (ENT-BLK ent)))
- (begin
- (fprintf
- diagout
- "PREV-BLK-ENT: I'm confused: at split key of blk %d:%ld"
- (ENT-SEG ent) (ENT-ID ent))
- (- (MATCH-POS pkt) 4))
- (+ 1 nxt-pos)))
- ACCREAD)
- goal-blk-num new-str k-len)))))
- ;;; get split key of this blk
- ))))))
-
- ;; FIND-PREV-ENT: called (like FIND-NEXT) with #f access on ENT.
- ;; Returns a new ENT with ACCREAD access. Will always return an ENT
- ;; unless some GET-ENT fails.
-
- (define (find-prev-ent ent desired-level last-level key-str k-len)
- (if trace-on
- (fprintf diagout "find-prev-ent dlevel=%d key=%.*s %d:%ld\\n"
- desired-level (max 0 k-len) key-str (ENT-SEG ent) (ENT-ID ent)))
- (and
- ent
- (ent-update-access ent #f ACCREAD) ;need to back out if #f
- (let ((blk (ENT-BLK ent)))
- (cond ((= (BLK-LEVEL blk) desired-level) ent)
- ((< (BLK-LEVEL blk) desired-level)
- (fprintf diagout ">>>>ERROR<<<< find-prev-ent: bad blk level\\n")
- #f)
- ((and (>= last-level 0)
- (not (= (BLK-LEVEL blk) (- last-level 1))))
- (fprintf diagout ">>>>ERROR<<<< find-prev-ent: bad blk level %d last=%d in %d:%ld\\n"
- (BLK-LEVEL blk) last-level (ENT-SEG ent) (ENT-ID ent))
- #f)
- (else
- (let ((pkt (make-vector PKT-SIZE)))
- (set! ent (chain-find ent ACCREAD key-str k-len pkt))
- (and ent
- (let* ((nxt-pos (next-field (ENT-BLK ent) (+ 1 (MATCH-POS pkt))))
- (ptr-pos (if (= nxt-pos (BLK-END (ENT-BLK ent)))
- (- (MATCH-POS pkt) 4)
- (+ 1 nxt-pos))))
- (if trace-on
- (fprintf diagout "find-prev-ent: at %d:%ld pos=%d next=%d ptrpos=%d\\n"
- (ENT-SEG ent) (ENT-ID ent) (MATCH-POS pkt) nxt-pos ptr-pos))
- (find-prev-ent
- (switch-ent ent ACCREAD
- (str2long (ENT-BLK ent) ptr-pos) #f)
- desired-level (BLK-LEVEL (ENT-BLK ent)) key-str k-len)))))))))
-